library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity link_tb is
end link_tb; 

architecture tb of link_tb is
  
  component link is

    port ( clk            		: in  std_logic;
           enable         		: in  std_logic;
           initialize     		: in  std_logic;
           reset_in       		: in  std_logic;
           link_data_in   		: in  std_logic;
           h_target_label 		: in  std_logic_vector(31 DownTo 0);
           reset_out      		: out std_logic;
           link_data_out  		: out std_logic;
           link_killed    		: out std_logic;
           b_position     		: out integer;
           b_label_current		: out std_logic_vector(31 DownTo 0); 
           link_complete  		: out std_logic
         );
    
  end component;

  -- Global Signals
  signal clk            : std_logic;
  signal link_a_to_b    : std_logic;

  -- link a specific signals
  signal init_a         		: std_logic;
  signal enable_a       		: std_logic;
  signal reset_a        		: std_logic;
  signal reset_out_a    		: std_logic;
  signal target_label_a 		: std_logic_vector(31 DownTo 0);
  signal data_out_a     		: std_logic;
  signal link_killed_a  		: std_logic;
  signal b_position_a   		: integer;
  signal b_label_current_a  : std_logic_vector(31 DownTo 0);
  signal link_complete_a		: std_logic;

  -- link b specific signals
  signal init_b         		: std_logic;
  signal enable_b       		: std_logic;
  signal reset_b        		: std_logic;
  signal reset_out_b    		: std_logic;
  signal target_label_b 		: std_logic_vector(31 DownTo 0);
  signal data_out_b     		: std_logic;
  signal link_killed_b  		: std_logic;
  signal b_position_b   		: integer;
  signal b_label_current_b  : std_logic_vector(31 DownTo 0);
  signal link_complete_b		: std_logic;
         
begin

  a_link : link port map ( clk, 
                           init_a, 
                           enable_a,
                           reset_a,
                           link_a_to_b,
                           target_label_a,
                           reset_out_a,
                           data_out_a,
                           link_killed_a,
                           b_position_a,
                           b_label_current_a,
                           link_complete_a
                         );

  b_link : link port map ( clk, 
                           init_b, 
                           enable_b,
                           reset_b,
                           link_a_to_b,
                           target_label_b,
                           reset_out_b,
                           data_out_b,
                           link_killed_b,
                           b_position_b,
                           b_label_current_b,
                           link_complete_b
                         );

  process

    variable out_loop : integer;
    variable in_loop : integer;

    procedure clock_link is
    begin
      clk <= '1';
      wait for 1 ns;
      clk <= '0';
      wait for 1 ns;
    end clock_link;

  begin

    init_a <= '1';
    init_b <= '1';
    wait for 1 ns;

    target_label_a <= "01001000100010001000100010001000";
    target_label_b <= "00001000100010001000100010001000";
    wait for 1 ns;

    reset_a <= '0';
    reset_b <= '0';
    wait for 1 ns;

    enable_a <= '1';
    enable_b <= '1';
    wait for 1 ns;

    for out_loop in 1 to 32 loop

      report ("Round: " & integer'image(out_loop));

      if ( out_loop = 10 ) then
        reset_a <= '1';
        wait for 1 ns;
      end if;

      clock_link;
      clock_link;

      -- link reset is read on this cycle

      clock_link;
      clock_link;
      clock_link;
      
      -- link data set on this clock cycle

      clock_link;
      clock_link;
      clock_link;

      report ("Link A Killed? " & std_logic'image(link_killed_a));
      report ("Link B Killed? " & std_logic'image(link_killed_b));

      report ("Link A Complete: " & std_logic'image(link_complete_a));
      report ("Link B Complete: " & std_logic'image(link_complete_b));

    end loop;

    wait;

  end process;


  data_link_set : process ( data_out_a, data_out_b )
  begin
      
    -- filter unitialized values
    if ( data_out_a = 'U' or data_out_b = 'U' ) then

    else 

      -- write link data if values exist
      link_a_to_b <= data_out_a or data_out_b;

    end if;

  end process data_link_set;

end tb;

